package com.wsm.common.aspect;

import com.wsm.common.domain.BlackipDO;
import com.wsm.common.domain.VisitDO;
import com.wsm.common.enums.BaseEnum;
import com.wsm.common.exception.LimitAcountException;
import com.wsm.common.service.BlackipService;
import com.wsm.common.service.RedisService;
import com.wsm.common.service.VisitService;
import com.wsm.common.utils.IPUtils;
import com.wsm.common.utils.UserAgentUtil;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.wsm.common.enums.Constant.*;

/**
 * @author wangshimin
 */
@Aspect
@Component
@Order(1)
public class VisistLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(VisistLogAspect.class);
    @Autowired
    RedisService redisService;
    @Autowired
    VisitService visitService;
    @Autowired
    BlackipService blackipService;


    @Pointcut("execution( * com.wsm.*.controller.*.*(..))")
    public void visitLogPointCut() {
    }

    @Before("visitLogPointCut()")
    public void before() throws Throwable {
        //验证黑名单
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String ip = IPUtils.getIpAddr(request);
        String limitkey = LIMIT_KEY + ip;
        if (redisService.hasKey(limitkey)) {
            logger.info("ip地址为{} 已被加入黑名单", ip);
            throw new LimitAcountException("禁止访问");
        }
        saveVisitLog(request, ip);
    }

    @Async
    void saveVisitLog(HttpServletRequest request, String ip) throws InterruptedException {
        String key = LIMIT_KEY_NUMBER + ip;
        if (redisService.hasKey(key)) {
            Long increment = redisService.increment(key);
            logger.info("ip地址为{} 登录次数为{}", ip, increment);
            if (increment > LIMIT_MAX_NUMBER) {
                String limitkey = LIMIT_KEY + ip;
                redisService.set(limitkey, 0);
                BlackipDO blackipDO = new BlackipDO();
                blackipDO.setIp(ip);
                blackipDO.setUseFlag(BaseEnum.USE_FLAG.YES.getCode());
                blackipDO.setDelFlag(1);
                blackipService.orSave(blackipDO);
                redisService.del(key);
                //加入黑名单
                logger.info("ip地址为{} 已被加入黑名单", ip);
            }
        } else {
            redisService.set(key, 0, 1, TimeUnit.MINUTES);
            String userAgent = request.getHeader("user-agent");
            VisitDO visitDO = new VisitDO();
            visitDO.setIp(ip);
            visitDO.setUseragent(userAgent);
            visitDO.setCity(IPUtils.getAddresses(ip));
            visitDO.setUrl(request.getServletPath());
            visitDO.setBrowsertype(UserAgentUtil.judgeBrowser(userAgent));
            visitDO.setPlatformtype(UserAgentUtil.platform(userAgent));
            visitDO.setGmtCreate(new Date());
            visitService.orSave(visitDO);
        }

    }
}
